`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2017/11/22 10:23:13
// Design Name: 
// Module Name: hazard
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module hazard(
	//fetch stage
	//output wire stallF,
	//decode stage
	input wire[4:0] rsD,rtD,
	input wire branchD,balD,jalD,jrD,
	output wire forwardaD,forwardbD,
	//output wire stallD,
	//execute stage
	input wire[4:0] rsE,rtE,
	input wire[4:0] writeregE,
	input wire regwriteE,
	input wire memtoregE,
	output reg[1:0] forwardaE,forwardbE,
	input wire stall_divE,
	//output wire flushE,
	input mfhiE,mfloE,//yyx
	output [2:0] forwardhlE,//yyx
	//mem stage
	input wire[4:0] writeregM,
	input wire regwriteM,
	input wire memtoregM,
	input hi_writeM,lo_writeM,//yyx
	//write back stage
	input wire[4:0] writeregW,
	input wire regwriteW,
	input hi_writeW,lo_writeW,//yyx

	output stallF, stallD, stallE,
    output flushF, flushD, flushE
    );

	wire lwstallD,branchstallD,jrstallD;

	//forwarding sources to D stage (branch equality)
	assign forwardaD = (rsD != 0 & rsD == writeregM & regwriteM);
	assign forwardbD = (rtD != 0 & rtD == writeregM & regwriteM);
	
	// 检查hilo冒险：如果E阶段正在读hilo(mf)，且发现M或W阶段要写hilo(hi_write, lo_write)，则把对应的hi_i, lo_i前推，否则直接输出hi_o, lo_o
	assign forwardhlE = mfhiE ? (hi_writeM ? 3'b011 : 
                             	 hi_writeW ? 3'b101 :
                                 3'b001) :
                     	mfloE ? (lo_writeM ? 3'b100 :
                                 lo_writeW ? 3'b110 :
                                 3'b010) :
                        3'b000;

	//forwarding sources to E stage (ALU)
	always @(*) begin
		forwardaE = 2'b00;
		forwardbE = 2'b00;
		if(rsE != 0) begin
			/* code */
			if(rsE == writeregM & regwriteM) begin
				/* code */
				forwardaE = 2'b10;
			end else if(rsE == writeregW & regwriteW) begin
				/* code */
				forwardaE = 2'b01;
			end
		end
		if(rtE != 0) begin
			/* code */
			if(rtE == writeregM & regwriteM) begin
				/* code */
				forwardbE = 2'b10;
			end else if(rtE == writeregW & regwriteW) begin
				/* code */
				forwardbE = 2'b01;
			end
		end
	end


	//stalls
	assign #1 lwstallD = memtoregE & (rtE == rsD | rtE == rtD);
	assign #1 branchstallD = branchD &
				(regwriteE & 
				(writeregE == rsD | writeregE == rtD) |
				memtoregM &
				(writeregM == rsD | writeregM == rtD));
	assign #1 jrstallD = jrD & 
				regwriteE & (writeregE == rsD) | 
				memtoregM & (writeregM == rsD);
	
	assign #1 stallD = lwstallD | branchstallD | jrstallD | stall_divE;
	assign #1 stallF = stallD;
	assign #1 stallE = stall_divE;//乘除法时再判断
	assign #1 stallM = 1'b0;//temp
	assign #1 stallW = 1'b0;//temp
		//stalling D stalls all previous stages
	assign #1 flushE = lwstallD | branchstallD | jrstallD;
		//stalling D flushes next stage
	// Note: not necessary to stall D stage on store
  	//       if source comes from load;
  	//       instead, another bypass network could
  	//       be added from W to M
endmodule
